<!DOCTYPE html>
<html lang="zh_cn">
<head>
          <title>来玩魔王的咚</title>
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta charset="utf-8" />
        <!-- twitter card metadata -->
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="/images/mowang.png">
<meta name="twitter:site" content="">
<meta name="twitter:title" content="格式化输出（fmt包）">
<meta name="twitter:description" content="<p>fmt包：各种转义字符，占位符说明；使用示例：重复使用操作数，输出字节序列，指定宽度，宽度和精度，打印结构体，字符串对齐，动态控制宽度（缩进）</p>">
        <!-- OG Tags -->
<meta property="og:url" content="/gopl-pkg-fmt.html"/>
<meta property="og:title" content="来玩魔王的咚 | 格式化输出（fmt包）" />
<meta property="og:description" content="<p>fmt包：各种转义字符，占位符说明；使用示例：重复使用操作数，输出字节序列，指定宽度，宽度和精度，打印结构体，字符串对齐，动态控制宽度（缩进）</p>" />
        <!-- favicon -->
        <link rel="icon" type="image/png" href="/images/mowang.png">
        <!-- moment.js for date formatting -->
        <script src="/theme/js/moment.js"></script>
        <!-- css -->
        <link rel="stylesheet" type="text/css" href="/theme/css/main.css" />
        <!-- 左边的menu，如果页面高度不够，就跟着滚动，否则文章分类显示不全 -->
        <link rel="stylesheet" type="text/css" href="/theme/css/mycss/menu.css" />
		<script>
			
                /*! grunt-grunticon Stylesheet Loader - v2.1.2 | https://github.com/filamentgroup/grunticon | (c) 2015 Scott Jehl, Filament Group, Inc. | MIT license. */
    
    (function(e){function t(t,n,r,o){"use strict";function a(){for(var e,n=0;u.length>n;n++)u[n].href&&u[n].href.indexOf(t)>-1&&(e=!0);e?i.media=r||"all":setTimeout(a)}var i=e.document.createElement("link"),l=n||e.document.getElementsByTagName("script")[0],u=e.document.styleSheets;return i.rel="stylesheet",i.href=t,i.media="only x",i.onload=o||null,l.parentNode.insertBefore(i,l),a(),i}var n=function(r,o){"use strict";if(r&&3===r.length){var a=e.navigator,i=e.Image,l=!(!document.createElementNS||!document.createElementNS("http://www.w3.org/2000/svg","svg").createSVGRect||!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image","1.1")||e.opera&&-1===a.userAgent.indexOf("Chrome")||-1!==a.userAgent.indexOf("Series40")),u=new i;u.onerror=function(){n.method="png",n.href=r[2],t(r[2])},u.onload=function(){var e=1===u.width&&1===u.height,a=r[e&&l?0:e?1:2];n.method=e&&l?"svg":e?"datapng":"png",n.href=a,t(a,null,null,o)},u.src="",document.documentElement.className+=" grunticon"}};n.loadCSS=t,e.grunticon=n})(this);(function(e,t){"use strict";var n=t.document,r="grunticon:",o=function(e){if(n.attachEvent?"complete"===n.readyState:"loading"!==n.readyState)e();else{var t=!1;n.addEventListener("readystatechange",function(){t||(t=!0,e())},!1)}},a=function(e){return t.document.querySelector('link[href$="'+e+'"]')},c=function(e){var t,n,o,a,c,i,u={};if(t=e.sheet,!t)return u;n=t.cssRules?t.cssRules:t.rules;for(var l=0;n.length>l;l++)o=n[l].cssText,a=r+n[l].selectorText,c=o.split(");")[0].match(/US\-ASCII\,([^"']+)/),c&&c[1]&&(i=decodeURIComponent(c[1]),u[a]=i);return u},i=function(e){var t,o,a;o="data-grunticon-embed";for(var c in e)if(a=c.slice(r.length),t=n.querySelectorAll(a+"["+o+"]"),t.length)for(var i=0;t.length>i;i++)t[i].innerHTML=e[c],t[i].style.backgroundImage="none",t[i].removeAttribute(o);return t},u=function(t){"svg"===e.method&&o(function(){i(c(a(e.href))),"function"==typeof t&&t()})};e.embedIcons=i,e.getCSS=a,e.getIcons=c,e.ready=o,e.svgLoadedCallback=u,e.embedSVG=u})(grunticon,this);
                
                grunticon(["/theme/css/icons.data.svg.css", "/theme/css/icons.data.png.css", "/theme/css/icons.fallback.css"]);
            </script>
        <noscript><link href="/theme/css/icons.fallback.css" rel="stylesheet"></noscript>
        <!-- menu toggle javascript -->
        <script type="text/javascript">
            document.addEventListener("DOMContentLoaded", initMenu);
            
            function initMenu(){
                var menu = document.getElementById("menu");
                var menulink = document.getElementById("menu-link");
                menulink.addEventListener("click", function toggleMenu(){
                        window.event.preventDefault();
                        menulink.classList.toggle('active');
                        menu.classList.toggle('active');              
                    });
            };
        </script>
        <!-- 不蒜子 -->
        <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>

    <meta name="description" content="<p>fmt包：各种转义字符，占位符说明；使用示例：重复使用操作数，输出字节序列，指定宽度，宽度和精度，打印结构体，字符串对齐，动态控制宽度（缩进）</p>" />

    <meta name="tags" content="gopl" />
    <meta name="tags" content="fmt" />
  <!-- 替换部分base的样式，看文章时，要再宽一点，右边有很多空间可以撑开 -->
  <link rel="stylesheet" type="text/css" href="/theme/css/mycss/article.css" />

</head>
<body>
    <div role="banner" id="masthead">
        <header>
            <a href="/"><img src="/images/mowang.png" alt="McManus Logo"></a>
                <h1>来玩魔王的咚@骑士救兵</h1>
            <a href="#menu" id="menu-link">more stuff</a>
            <nav id="menu">
                <ul>
                        <li><a href="/tags">tags</a></li>
                            <li><a href="/category/cloud.html">Cloud</a></li>
                            <li><a href="/category/docker.html">Docker</a></li>
                            <li class="active"><a href="/category/go.html">Go</a></li>
                            <li><a href="/category/linux.html">Linux</a></li>
                            <li><a href="/category/python.html">Python</a></li>
                            <li><a href="/category/xue-xi-bi-ji.html">学习笔记</a></li>
                            <li><a href="/category/yun-wei-zi-dong-hua.html">运维自动化</a></li>
                </ul>
            </nav>
        </header>
    </div>
        <div class="page" role="main">
  <div class="article" role="article">
    <article>
        <footer>
            <a name="top"></a>
            <p>
              <time datetime=" 2020-07-11 11:50:00+08:00">
                <script>document.write(moment('2020-07-11 11:50:00+08:00').format('LL'));</script>
              </time>
              ~
              <time datetime=" 2020-07-11 11:50:00+08:00">
                <script>document.write(moment('2020-07-01 11:50:00+08:00').format('LL'));</script>
              </time>
            </p>
        </footer>
        <header>
          <h2>
            格式化输出（fmt包）
          </h2>
        </header>
      <div class="content">
         <div class="toc">
<ul>
<li><a href="#fmt-bao">fmt 包</a><ul>
<li><a href="#fmt-ge-shi-hua-shu-chu">fmt格式化输出</a></li>
<li><a href="#geng-xiang-xi-de-zhan-wei-fu-shuo-ming">更详细的占位符说明</a></li>
</ul>
</li>
<li><a href="#shi-yong-shi-li">使用示例</a><ul>
<li><a href="#fmt-de-liang-ge-ji-qiao">fmt的两个技巧</a></li>
<li><a href="#shu-chu-zi-jie-xu-lie">输出字节序列</a></li>
<li><a href="#zhi-ding-kuan-du">指定宽度</a></li>
<li><a href="#kuan-du-he-jing-du">宽度和精度</a></li>
<li><a href="#da-yin-jie-gou-ti">打印结构体</a></li>
<li><a href="#zi-fu-chuan-dui-qi">字符串对齐</a></li>
<li><a href="#dong-tai-kong-zhi-kuan-du-suo-jin">动态控制宽度（缩进）</a></li>
</ul>
</li>
</ul>
</div>
<h3 id="fmt-bao"><a class="toclink" href="#fmt-bao">fmt 包</a></h3>
<p>功能：fmt包实现了类似C语言printf和scanf的格式化I/O。格式化动作（'verb'）源自C语言但更简单。  </p>
<h4 id="fmt-ge-shi-hua-shu-chu"><a class="toclink" href="#fmt-ge-shi-hua-shu-chu">fmt格式化输出</a></h4>
<p>Printf 函数有超过10个各种转义字符，Go 程序员称为 verb。下表不完整，但是它说明了很多可用的功能：</p>
<table>
<thead>
<tr>
<th>verb</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>%d</td>
<td>十进制数</td>
</tr>
<tr>
<td>%x, %o, %b</td>
<td>十六进制，八进制，二进制数</td>
</tr>
<tr>
<td>%f, %g, %e</td>
<td>浮点数</td>
</tr>
<tr>
<td>%t</td>
<td>布尔型</td>
</tr>
<tr>
<td>%c</td>
<td>字符（Unicode码点）</td>
</tr>
<tr>
<td>%s</td>
<td>字符串</td>
</tr>
<tr>
<td>%q</td>
<td>带引号字符串或者字符</td>
</tr>
<tr>
<td>%v</td>
<td>内置格式的任何值</td>
</tr>
<tr>
<td>%T</td>
<td>任何值的类型</td>
</tr>
<tr>
<td>%w</td>
<td>Go1.13后新增的用于输出error</td>
</tr>
<tr>
<td>%%</td>
<td>百分号本身</td>
</tr>
</tbody>
</table>
<p>以ln结尾的，比如fmt.Println，使用%v的方式来格式化参数，并且在最后追加换行符。  </p>
<h4 id="geng-xiang-xi-de-zhan-wei-fu-shuo-ming"><a class="toclink" href="#geng-xiang-xi-de-zhan-wei-fu-shuo-ming">更详细的占位符说明</a></h4>
<p>上面的表格比较概括，而且也不全，对于不同的类型，还有不同的细节。所有的说明都在fmt包的doc.go文档里有详细的说明：<br>
http://docscn.studygolang.com/src/fmt/doc.go  </p>
<h5 id="pu-tong-zhan-wei-fu"><a class="toclink" href="#pu-tong-zhan-wei-fu">普通占位符</a></h5>
<table>
<thead>
<tr>
<th>占位符</th>
<th>说明</th>
<th>举例</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr>
<td>%v</td>
<td>相应值的默认格式。</td>
<td>Printf("%v", people)</td>
<td>{zhangsan}</td>
</tr>
<tr>
<td>%+v</td>
<td>打印结构体时，会添加字段名</td>
<td>Printf("%+v", people)</td>
<td>{Name:zhangsan}</td>
</tr>
<tr>
<td>%#v</td>
<td>相应值的Go语法表示</td>
<td>Printf("%#v", people)</td>
<td>main.Human{Name:"zhangsan"}</td>
</tr>
<tr>
<td>%T</td>
<td>相应值的类型的Go语法表示</td>
<td>Printf("%T", people)</td>
<td>main.Human</td>
</tr>
<tr>
<td>%%</td>
<td>字面上的百分号，并非值的占位符</td>
<td>Printf("%%")</td>
<td>%</td>
</tr>
</tbody>
</table>
<h5 id="bu-er-zhan-wei-fu"><a class="toclink" href="#bu-er-zhan-wei-fu">布尔占位符</a></h5>
<table>
<thead>
<tr>
<th>占位符</th>
<th>说明</th>
<th>举例</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr>
<td>%t</td>
<td>true 或 false。</td>
<td>Printf("%t", true)</td>
<td>true</td>
</tr>
</tbody>
</table>
<h5 id="zheng-shu-zhan-wei-fu"><a class="toclink" href="#zheng-shu-zhan-wei-fu">整数占位符</a></h5>
<table>
<thead>
<tr>
<th>占位符</th>
<th>说明</th>
<th>举例</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr>
<td>%b</td>
<td>二进制表示</td>
<td>Printf("%b", 5)</td>
<td>101</td>
</tr>
<tr>
<td>%c</td>
<td>相应Unicode码点所表示的字符</td>
<td>Printf("%c", 0x4E2D)</td>
<td>中</td>
</tr>
<tr>
<td>%d</td>
<td>十进制表示</td>
<td>Printf("%d", 0x12)</td>
<td>18</td>
</tr>
<tr>
<td>%o</td>
<td>八进制表示</td>
<td>Printf("%d", 10)</td>
<td>12</td>
</tr>
<tr>
<td>%q</td>
<td>单引号围绕的字符字面值，由Go语法安全地转义</td>
<td>Printf("%q", 0x4E2D)</td>
<td>'中'</td>
</tr>
<tr>
<td>%x</td>
<td>十六进制表示，字母形式为小写 a-f</td>
<td>Printf("%x", 13)</td>
<td>d</td>
</tr>
<tr>
<td>%X</td>
<td>十六进制表示，字母形式为大写 A-F</td>
<td>Printf("%x", 13)</td>
<td>D</td>
</tr>
<tr>
<td>%U</td>
<td>Unicode格式，相当于 "%04X" 加上前导 "U+"</td>
<td>Printf("%U", 0x4E2D)</td>
<td>U+4E2D</td>
</tr>
</tbody>
</table>
<h5 id="fu-dian-shu-he-fu-shu"><a class="toclink" href="#fu-dian-shu-he-fu-shu">浮点数和复数</a></h5>
<table>
<thead>
<tr>
<th>占位符</th>
<th>说明</th>
<th>举例</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr>
<td>%b</td>
<td>无小数部分的，指数为二的幂的科学计数法，与 strconv.FormatFloat 的 'b' 转换格式一致。例如 -123456p-78</td>
<td></td>
<td></td>
</tr>
<tr>
<td>%e</td>
<td>科学计数法，例如 -1234.456e+78</td>
<td>Printf("%e", 10.2)</td>
<td>1.020000e+01</td>
</tr>
<tr>
<td>%E</td>
<td>科学计数法，例如 -1234.456E+78</td>
<td>Printf("%e", 10.2)</td>
<td>1.020000E+01</td>
</tr>
<tr>
<td>%f</td>
<td>有小数点而无指数，例如 123.456</td>
<td>Printf("%f", 10.2)</td>
<td>10.200000</td>
</tr>
<tr>
<td>%g</td>
<td>根据情况选择 %e 或 %f 以产生更紧凑的（无末尾的0）输出</td>
<td>Printf("%g", 10.20)</td>
<td>10.2</td>
</tr>
<tr>
<td>%G</td>
<td>根据情况选择 %E 或 %f 以产生更紧凑的（无末尾的0）输出</td>
<td>Printf("%G", 10.20+2i)</td>
<td>(10.2+2i)</td>
</tr>
</tbody>
</table>
<h5 id="zhi-zhen"><a class="toclink" href="#zhi-zhen">指针</a></h5>
<table>
<thead>
<tr>
<th>占位符</th>
<th>说明</th>
<th>举例</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr>
<td>%p</td>
<td>十六进制表示，前缀 0x</td>
<td>Printf("%p", &amp;people)</td>
<td>0x4f57f0</td>
</tr>
</tbody>
</table>
<h5 id="qi-ta-biao-ji-fu-ci"><a class="toclink" href="#qi-ta-biao-ji-fu-ci">其他标记（副词）</a></h5>
<ul>
<li>"+" ： 总打印数值的正负号；对于%q（%+q）保证只输出字符的编码。<code>fmt.Printf("%q %+[1]q\n", "中文") // "中文" "\u4e2d\u6587"</code></li>
<li>"-" ： 在右侧而非左侧填充空格（左对齐该区域）</li>
<li>" " ： (空格)为数值中省略的正负号留出空白（% d）； 以十六进制（% x, % X）打印字符串或切片时，在字节之间用空格隔开</li>
<li>"0" ： 填充前导的0而非空格；对于数字，这会将填充移到正负号之后</li>
<li>"#" ： 备用格式，不同的类型还不一样。</li>
<li>"*" ： 使用一个变量来控制输出的宽度，实现可变宽度。</li>
</ul>
<p>副词#的备用格式：<br>
八进制、十六进制，默认没有前导，使用#后会添加前导符号"0"、"0x"、"0X"，防止产生歧义：</p>
<div class="highlight"><pre><span></span><code><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%o %#[1]o\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">123</span><span class="p">)</span><span class="w">        </span><span class="c1">// 173 0173</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%x %#[1]x %#[1]X\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">123</span><span class="p">)</span><span class="w"> </span><span class="c1">// 7b 0x7b 0X7B</span><span class="w"></span>
</code></pre></div>

<p>指针默认有前导，备用格式就是就掉前导：</p>
<div class="highlight"><pre><span></span><code><span class="kd">var</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="kt">string</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%p %#[1]p\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="nx">s</span><span class="p">)</span><span class="w"> </span><span class="c1">// 0xc00004c240 c00004c240</span><span class="w"></span>
</code></pre></div>

<p>对于字符串，%#q有些情况下会输出反引号围绕的字符串，不过测试下来不总是这样：</p>
<div class="highlight"><pre><span></span><code><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%q, %#[1]q\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;ab\tcd&quot;</span><span class="p">)</span><span class="w"> </span><span class="c1">// &quot;ab\tcd&quot;, `ab   cd`</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%q, %#[1]q\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;ab\ncd&quot;</span><span class="p">)</span><span class="w"> </span><span class="c1">// &quot;ab\ncd&quot;, &quot;ab\ncd&quot;</span><span class="w"></span>
</code></pre></div>

<p>对于Unicode，打印出字符的编码后还会打印该字符：</p>
<div class="highlight"><pre><span></span><code><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%U, %#[1]U&quot;</span><span class="p">,</span><span class="w"> </span><span class="sc">&#39;中&#39;</span><span class="p">)</span><span class="w"> </span><span class="c1">// U+4E2D, U+4E2D &#39;中&#39;</span><span class="w"></span>
</code></pre></div>

<h3 id="shi-yong-shi-li"><a class="toclink" href="#shi-yong-shi-li">使用示例</a></h3>
<p>下面是一些可以通过合理的构造格式化字符串来打到最佳的显示效果的示例。<br>
可能有些示例之间会有点重复。还有一些示例因为太简单，感觉上一节已经讲过了。不过上一节的介绍偏理论，而这里的内容更注重实际使用。  </p>
<h4 id="fmt-de-liang-ge-ji-qiao"><a class="toclink" href="#fmt-de-liang-ge-ji-qiao">fmt的两个技巧</a></h4>
<p>一、%后的副词[1]告知Printf重复使用第一个操作数。<br>
二、%o、%x、%X之前的副词#告知Printf输出相应的前缀 0、0x、0X。  </p>
<div class="highlight"><pre><span></span><code><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">o</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mo">0666</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%d %[1]o %#[1]o\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">o</span><span class="p">)</span><span class="w">  </span><span class="c1">// 438 666 0666</span><span class="w"></span>
<span class="w">    </span><span class="nx">x</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nb">int64</span><span class="p">(</span><span class="mh">0xdeadbeef</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%d %[1]x %#[1]x %#[1]X\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="p">)</span><span class="w">  </span><span class="c1">// 3735928559 deadbeef 0xdeadbeef 0XDEADBEEF</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>

<h4 id="shu-chu-zi-jie-xu-lie"><a class="toclink" href="#shu-chu-zi-jie-xu-lie">输出字节序列</a></h4>
<p>使用%x可以输出字节序列的UTF-8编码，还可以加上空格也就是% x，这样每个字符还能隔开，在对字节序列进行输出的时候特别有用：</p>
<div class="highlight"><pre><span></span><code><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%x\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;abcdefg&quot;</span><span class="p">)</span><span class="w">   </span><span class="c1">// &quot;61626364656667&quot;</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;% x\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;abcdefg&quot;</span><span class="p">)</span><span class="w">  </span><span class="c1">// &quot;61 62 63 64 65 66 67&quot;</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;% #x\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;abcdefg&quot;</span><span class="p">)</span><span class="w"> </span><span class="c1">// &quot;0x61 0x62 0x63 0x64 0x65 0x66 0x67&quot;</span><span class="w"></span>
</code></pre></div>

<p>对于Unicode字符，还是按照字节处理的，如若要输出Unicode码点，需要先转成[]rune类型：</p>
<div class="highlight"><pre><span></span><code><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;% x\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;世界&quot;</span><span class="p">)</span><span class="w">        </span><span class="c1">// &quot;e4 b8 96 e7 95 8c&quot;</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%x\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="p">[]</span><span class="nb">rune</span><span class="p">(</span><span class="s">&quot;世界&quot;</span><span class="p">))</span><span class="w"> </span><span class="c1">// &quot;[4e16 754c]&quot;</span><span class="w"></span>
</code></pre></div>

<h4 id="zhi-ding-kuan-du"><a class="toclink" href="#zhi-ding-kuan-du">指定宽度</a></h4>
<p>通过指定相同的宽度，可以做到右对齐的效果：</p>
<div class="highlight"><pre><span></span><code><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%4d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%4d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%4d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">100</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%4d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">1000</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%4d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">10000</span><span class="p">)</span><span class="w">  </span><span class="c1">// 这个会超出宽度</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 输出结果</span>
<span class="cm">$ go run main.go</span>
<span class="cm">   1</span>
<span class="cm">  10</span>
<span class="cm"> 100</span>
<span class="cm">1000</span>
<span class="cm">10000</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>

<p><em>这里的页面似乎看不出对齐的效果，可能是空格的宽度不太一样。下面使用0填充的对齐效果就有了</em><br>
如果宽度不够，输出时也不会丢失信息，而是把信息全部输出，不受宽度的限制。<br>
默认使用空格填充，也可以指定填充的内容，比如使用0填充，在输出二进制数的时候非常有用：</p>
<div class="highlight"><pre><span></span><code><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%04b\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%04b\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%04b\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%04b\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%04b\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="mi">666</span><span class="p">)</span><span class="w">  </span><span class="c1">// 这个会超出宽度</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 输出结果</span>
<span class="cm">$ go run main.go</span>
<span class="cm">0001</span>
<span class="cm">0010</span>
<span class="cm">0011</span>
<span class="cm">0100</span>
<span class="cm">1010011010</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>

<h4 id="kuan-du-he-jing-du"><a class="toclink" href="#kuan-du-he-jing-du">宽度和精度</a></h4>
<p>操作数字的时候，宽度为该数值占用区域的最小宽度；精度为小数点之后的位数。<br>
对于 %g 和 %G 精度是所有数字的总和，而用 %f 打印出来同样是小数，精度是小数点后面的位数。比如：123.45，%.4g 是 "123.5" 而 %.2f 是 "123.45"。  </p>
<div class="highlight"><pre><span></span><code><span class="kd">const</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="kt">float64</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="mf">123.45</span><span class="w"></span>
<span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%.4g %.2[1]f&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="c1">// g:123.5 f:123.45</span><span class="w"></span>
</code></pre></div>

<h4 id="da-yin-jie-gou-ti"><a class="toclink" href="#da-yin-jie-gou-ti">打印结构体</a></h4>
<p>打印结构体的时候，使用副词#或者+可以使结构化符号%v以类似Go语法的方式输出对象，这个方法里面包含了成员变量的名字：</p>
<div class="highlight"><pre><span></span><code><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w"></span>

<span class="kn">import</span><span class="w"> </span><span class="s">&quot;fmt&quot;</span><span class="w"></span>

<span class="c1">// 这可以表示一个坐标</span><span class="w"></span>
<span class="kd">type</span><span class="w"> </span><span class="nx">Point</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">X</span><span class="p">,</span><span class="w"> </span><span class="nx">Y</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="c1">// 坐标加上半径就是一个圆</span><span class="w"></span>
<span class="kd">type</span><span class="w"> </span><span class="nx">Circle</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">Point</span><span class="w"></span>
<span class="w">    </span><span class="nx">Radius</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="c1">// 圆加上辐条数，这表示一个轮子</span><span class="w"></span>
<span class="kd">type</span><span class="w"> </span><span class="nx">Wheel</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">Circle</span><span class="w"></span>
<span class="w">    </span><span class="nx">Spokes</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="kd">var</span><span class="w"> </span><span class="nx">w</span><span class="w"> </span><span class="nx">Wheel</span><span class="w"></span>

<span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">w</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">Wheel</span><span class="p">{</span><span class="nx">Circle</span><span class="p">{</span><span class="nx">Point</span><span class="p">{</span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="p">},</span><span class="w"> </span><span class="mi">5</span><span class="p">},</span><span class="w"> </span><span class="mi">20</span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="nx">w</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">Wheel</span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">Circle</span><span class="p">:</span><span class="w"> </span><span class="nx">Circle</span><span class="p">{</span><span class="w"></span>
<span class="w">            </span><span class="nx">Point</span><span class="p">:</span><span class="w">  </span><span class="nx">Point</span><span class="p">{</span><span class="nx">X</span><span class="p">:</span><span class="w"> </span><span class="mi">8</span><span class="p">,</span><span class="w"> </span><span class="nx">Y</span><span class="p">:</span><span class="w"> </span><span class="mi">8</span><span class="p">},</span><span class="w"></span>
<span class="w">            </span><span class="nx">Radius</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"></span>
<span class="w">        </span><span class="p">},</span><span class="w"></span>
<span class="w">        </span><span class="nx">Spokes</span><span class="p">:</span><span class="w"> </span><span class="mi">20</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%v\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">w</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%#v\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">w</span><span class="p">)</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 执行结果</span>
<span class="cm">PS H:\Go\src\gopl\ch4\embed&gt; go run main.go</span>
<span class="cm">{{{8 8} 5} 20}</span>
<span class="cm">main.Wheel{Circle:main.Circle{Point:main.Point{X:8, Y:8}, Radius:5}, Spokes:20}</span>
<span class="cm">PS H:\Go\src\gopl\ch4\embed&gt;</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>

<h4 id="zi-fu-chuan-dui-qi"><a class="toclink" href="#zi-fu-chuan-dui-qi">字符串对齐</a></h4>
<p>宽度和精度对于字符串输出同样有效：</p>
<ul>
<li>宽度为输出的最小字符数，如果必要的话会为已格式化的形式填充空格。</li>
<li>精度为输出的最大字符数，如果必要的话会直接截断。</li>
</ul>
<p>这样就可以在输出字符串的时候做到左对齐和右对齐，输出类似表格的样式：</p>
<div class="highlight"><pre><span></span><code><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w"></span>

<span class="kn">import</span><span class="w"> </span><span class="s">&quot;fmt&quot;</span><span class="w"></span>

<span class="kd">type</span><span class="w"> </span><span class="nx">message</span><span class="w"> </span><span class="kd">struct</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">Title</span><span class="w"> </span><span class="kt">string</span><span class="w"></span>
<span class="w">    </span><span class="nx">text</span><span class="w">  </span><span class="kt">string</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">list</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">[]</span><span class="nx">message</span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">{</span><span class="s">&quot;fmt&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Package fmt implements formatted I/O with functions analogous to C&#39;s printf and scanf. The format &#39;verbs&#39; are derived from C&#39;s but are simpler. &quot;</span><span class="p">},</span><span class="w"></span>
<span class="w">        </span><span class="p">{</span><span class="s">&quot;bytes&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Package bytes implements functions for the manipulation of byte slices. It is analogous to the facilities of the strings package. &quot;</span><span class="p">},</span><span class="w"></span>
<span class="w">        </span><span class="p">{</span><span class="s">&quot;time&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Package time provides functionality for measuring and displaying time. &quot;</span><span class="p">},</span><span class="w"></span>
<span class="w">        </span><span class="p">{</span><span class="s">&quot;net/http&quot;</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;Package http provides HTTP client and server implementations. &quot;</span><span class="p">},</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="nx">_</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">list</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">msg</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">list</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%9.9s %.99s\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">msg</span><span class="p">.</span><span class="nx">Title</span><span class="p">,</span><span class="w"> </span><span class="nx">msg</span><span class="p">.</span><span class="nx">text</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 输出效果</span>
<span class="cm">PS H:\Go\src\gopl\output&gt; go run main.go</span>
<span class="cm">      fmt Package fmt implements formatted I/O with functions analogous to C&#39;s printf and scanf. The format &#39;</span>
<span class="cm">    bytes Package bytes implements functions for the manipulation of byte slices. It is analogous to the faci</span>
<span class="cm">     time Package time provides functionality for measuring and displaying time.</span>
<span class="cm"> net/http Package http provides HTTP client and server implementations.</span>
<span class="cm">PS H:\Go\src\gopl\output&gt;</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>

<p>不过对于中文输出就不会那么漂亮了，因为这里填充的空格是半角的空格。  </p>
<h5 id="zi-fu-chuan-zuo-dui-qi"><a class="toclink" href="#zi-fu-chuan-zuo-dui-qi">字符串左对齐</a></h5>
<p>其实只要用上制表符\t就能对齐了，不过如果字符串的长度相差比较大，也无法对齐，并且间隔是自动的。下面是另一种精确的实现方法。<br>
默认是在前面进行填充，似乎也没有在后面填充的格式。不过可以用下面的方法输出左对齐的效果：</p>
<div class="highlight"><pre><span></span><code><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%s%*s %.99s\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">msg</span><span class="p">.</span><span class="nx">Title</span><span class="p">,</span><span class="w"> </span><span class="mi">10</span><span class="o">-</span><span class="nb">len</span><span class="p">(</span><span class="nx">msg</span><span class="p">.</span><span class="nx">Title</span><span class="p">),</span><span class="w"> </span><span class="s">&quot;&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">msg</span><span class="p">.</span><span class="nx">text</span><span class="p">)</span><span class="w"></span>
</code></pre></div>

<p>这里的<code>%*s</code>是在s对应的内容输出前，动态的填充由变量指定的前导空格。由于这里s对应的是空字符串，所以就相当于是动态添加空格，而空格的数量是可以根据前一个变量的长度计算后动态变化的。这是下一节的内容，不过这里正好先展示下效果。  </p>
<h4 id="dong-tai-kong-zhi-kuan-du-suo-jin"><a class="toclink" href="#dong-tai-kong-zhi-kuan-du-suo-jin">动态控制宽度（缩进）</a></h4>
<p>还有一种控制宽度的方法，使用*号，这种方式输出的宽度是由之后的变量决定的所以是可变的：</p>
<div class="highlight"><pre><span></span><code><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%*d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="o">*</span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 执行结果</span>
<span class="cm">PS H:\Go\src\gopl\output&gt; go run main.go</span>
<span class="cm">0</span>
<span class="cm">   1</span>
<span class="cm">       2</span>
<span class="cm">PS H:\Go\src\gopl\output&gt; go run main.go</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>

<p>输出的宽度由第一个变量控制，而输出的内容是第二个变量。  </p>
<p>这里加了个0，这样就用0来代替原来的空格来填补宽度了，下面显示的效果更加直观：</p>
<div class="highlight"><pre><span></span><code><span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="p">&lt;</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%0*d\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="o">*</span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 执行结果</span>
<span class="cm">PS H:\Go\src\gopl\output&gt; go run main.go</span>
<span class="cm">0</span>
<span class="cm">0001</span>
<span class="cm">00000002</span>
<span class="cm">PS H:\Go\src\gopl\output&gt;</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>

<p>由于宽度是包含字符串本身的，而缩进效果是不包括字符串的。所以可是使用空字符串作为第二个参数，把要输出的内容放在后面。  </p>
<p>推荐这么用，<code>fmt.Printf("%*s&lt;%s&gt;\n", n*2, "", "div")</code> 第一个变量控制宽度，第二个是输出的字符串，这里是空字符串，这里就是两格缩进的效果。把要输出的内容放在后面，这里的第三个变量。<br>
这种显示效果在处理代码和html标签的时候特别好，下面的程序先通过Get请求获取一个页面，然后解析页面中的文档树，并输出有缩进效果的树结构：</p>
<div class="highlight"><pre><span></span><code><span class="kn">package</span><span class="w"> </span><span class="nx">main</span><span class="w"></span>

<span class="kn">import</span><span class="w"> </span><span class="p">(</span><span class="w"></span>
<span class="w">    </span><span class="s">&quot;fmt&quot;</span><span class="w"></span>
<span class="w">    </span><span class="s">&quot;net/http&quot;</span><span class="w"></span>
<span class="w">    </span><span class="s">&quot;os&quot;</span><span class="w"></span>

<span class="w">    </span><span class="s">&quot;golang.org/x/net/html&quot;</span><span class="w"></span>
<span class="p">)</span><span class="w"></span>

<span class="kd">func</span><span class="w"> </span><span class="nx">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">url</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="k">range</span><span class="w"> </span><span class="nx">os</span><span class="p">.</span><span class="nx">Args</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">outline</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="kd">func</span><span class="w"> </span><span class="nx">outline</span><span class="p">(</span><span class="nx">url</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="kt">error</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nx">resp</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">http</span><span class="p">.</span><span class="nx">Get</span><span class="p">(</span><span class="nx">url</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="k">defer</span><span class="w"> </span><span class="nx">resp</span><span class="p">.</span><span class="nx">Body</span><span class="p">.</span><span class="nx">Close</span><span class="p">()</span><span class="w"></span>

<span class="w">    </span><span class="nx">doc</span><span class="p">,</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">html</span><span class="p">.</span><span class="nx">Parse</span><span class="p">(</span><span class="nx">resp</span><span class="p">.</span><span class="nx">Body</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">err</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">err</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="nx">forEachNode</span><span class="p">(</span><span class="nx">doc</span><span class="p">,</span><span class="w"> </span><span class="nx">startElement</span><span class="p">,</span><span class="w"> </span><span class="nx">endElement</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="kc">nil</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="c1">// 调用 pre(x) 和 post(x) 遍历以n为根的树中的每个节点x</span><span class="w"></span>
<span class="c1">// 两个函数都是可选的</span><span class="w"></span>
<span class="c1">// pre 在子节点被访问前调用（前序调用）</span><span class="w"></span>
<span class="c1">// post  在访问后调用（后续调用）</span><span class="w"></span>
<span class="kd">func</span><span class="w"> </span><span class="nx">forEachNode</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">*</span><span class="nx">html</span><span class="p">.</span><span class="nx">Node</span><span class="p">,</span><span class="w"> </span><span class="nx">pre</span><span class="p">,</span><span class="w"> </span><span class="nx">post</span><span class="w"> </span><span class="kd">func</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">*</span><span class="nx">html</span><span class="p">.</span><span class="nx">Node</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">pre</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">pre</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">n</span><span class="p">.</span><span class="nx">FirstChild</span><span class="p">;</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="p">;</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="nx">c</span><span class="p">.</span><span class="nx">NextSibling</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">forEachNode</span><span class="p">(</span><span class="nx">c</span><span class="p">,</span><span class="w"> </span><span class="nx">pre</span><span class="p">,</span><span class="w"> </span><span class="nx">post</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">post</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="kc">nil</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">post</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="kd">var</span><span class="w"> </span><span class="nx">depth</span><span class="w"> </span><span class="kt">int</span><span class="w"></span>

<span class="kd">func</span><span class="w"> </span><span class="nx">startElement</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">*</span><span class="nx">html</span><span class="p">.</span><span class="nx">Node</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">n</span><span class="p">.</span><span class="nx">Type</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">html</span><span class="p">.</span><span class="nx">ElementNode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%*s&lt;%s&gt;\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">depth</span><span class="o">*</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span><span class="w"></span>
<span class="w">        </span><span class="nx">depth</span><span class="o">++</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="kd">func</span><span class="w"> </span><span class="nx">endElement</span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">*</span><span class="nx">html</span><span class="p">.</span><span class="nx">Node</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="nx">n</span><span class="p">.</span><span class="nx">Type</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="nx">html</span><span class="p">.</span><span class="nx">ElementNode</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="nx">depth</span><span class="o">--</span><span class="w"></span>
<span class="w">        </span><span class="nx">fmt</span><span class="p">.</span><span class="nx">Printf</span><span class="p">(</span><span class="s">&quot;%*s&lt;/%s&gt;\n&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">depth</span><span class="o">*</span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="s">&quot;&quot;</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">.</span><span class="nx">Data</span><span class="p">)</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cm">/* 执行结果</span>
<span class="cm">PS H:\Go\src\gopl\ch5\outline2&gt; go run main.go http://baidu.com</span>
<span class="cm">&lt;html&gt;</span>
<span class="cm">  &lt;head&gt;</span>
<span class="cm">    &lt;meta&gt;</span>
<span class="cm">    &lt;/meta&gt;</span>
<span class="cm">  &lt;/head&gt;</span>
<span class="cm">  &lt;body&gt;</span>
<span class="cm">  &lt;/body&gt;</span>
<span class="cm">&lt;/html&gt;</span>
<span class="cm">PS H:\Go\src\gopl\ch5\outline2&gt;</span>
<span class="cm">*/</span><span class="w"></span>
</code></pre></div>
      </div>
      <div class="back-to-top">
        <a href="/">HOME</a>
        <a href="#top">TOP</a>
      </div>
    </article>
  </div>
<!-- end article -->
<!-- 页面往下滚动一段之后才会显示TOC -->
<script>
  window.onscroll = function() {
    var tocbox = document.getElementsByClassName('toc')[0];
    var osTop = document.documentElement.scrollTop || document.body.scrollTop;
    var osWidth = document.documentElement.scrollWidth || document.body.scrollWidth;
    // console.log(osTop)
    if (osTop>300 && osWidth>865) {
      tocbox.style.display = "block"
    }
    if (osTop<300 || osWidth<865) {
      tocbox.style.display = "none"
    }
  }
</script>
                <footer>
                    <div class="icons">
                    </div>
                    <span id="busuanzi_container_page_pv" style="padding: 10px">本文阅读量<span id="busuanzi_value_page_pv"></span>次</span>
                    <span id="busuanzi_container_site_pv" style="padding: 10px">本站总访问量<span id="busuanzi_value_site_pv"></span>次</span>
                    <span id="busuanzi_container_site_uv" style="padding: 10px">本站总访客数<span id="busuanzi_value_site_uv"></span>人</span>
                    <p>© <script>document.write(moment().format('YYYY'));</script> 749B</p>
                </footer>
        </div>
</body>
</html>